#!/usr/bin/env python
from elixir import *
import settings,zlib
from sqlalchemy.databases.mysql import MSInteger,MSFloat,MSBlob,MSTinyInteger,MSChar

metadata.bind=settings.SQLBind

def _dic2cmd(dic1):
    stm=''
    for k1,v1 in dic1.items():
        stm+='%s=Field(%s)\n'%(k1,v1)
    return stm

def _updatetag(tablename,pk,pkv,**argv):
    runflag=False
    cmd='update %s set '%tablename
    if argv.has_key('status'):
        runflag=True
        cmd+='status=%s '%argv['status']
    if argv.has_key('tag'):
        runflag=True
        cmd+=',tag="%s" '%argv['tag']
    if runflag:
        metadata.bind.execute(cmd+'where %s=%s'%(pk,pkv))

class MOL(Entity):
    using_options(tablename=settings.MoleculeTableName,autosetup=True)

    exec(_dic2cmd(settings.MoleColumn))
        
    molfile=Field(BLOB,deferred=True)
    poses=OneToMany('POSE')
    tag=OneToOne('MOLTAG')
    
    def PDB(self):
        return zlib.decompress(self.molfile)
    
    def writePDB(self,pdbfilename):
        f=open(pdbfilename,'w')
        f.write(self.PDB())
        f.close()
    
    def loadPDB(self,pdbfilename):
        f=open(pdbfilename)
        fpdbstr=f.read()
        f.close()
        fpdbstrcomp=zlib.compress(fpdbstr)
        self.molfile=fpdbstrcomp
        session.flush()

# Temo table for transfer
class MOLOLD(Entity):
    using_options(tablename='zincmolold',autosetup=True)
    
    zincid=Field(MSInteger(8,unsigned=True),primary_key=True)
    pacname=Field(MSChar(3))
    numatoms=Field(MSTinyInteger(3,unsigned=True),)
    numc=Field(MSTinyInteger(3,unsigned=True),)
    numn=Field(MSTinyInteger(3,unsigned=True),)
    numo=Field(MSTinyInteger(3,unsigned=True),)
    numhal=Field(MSTinyInteger(3,unsigned=True),)
    nums=Field(MSTinyInteger(3,unsigned=True),)
    nump=Field(MSTinyInteger(3,unsigned=True),)
    numarombnd=Field(MSTinyInteger(3,unsigned=True),)
    numdoubbnd=Field(MSTinyInteger(3,unsigned=True),)
    numtribnd=Field(MSTinyInteger(3,unsigned=True),)
    numamibnd=Field(MSTinyInteger(3,unsigned=True),)
    numacc=Field(MSTinyInteger(3,unsigned=True),)
    numdon=Field(MSTinyInteger(3,unsigned=True),)
    numring=Field(MSTinyInteger(3,unsigned=True),)
    totringsize=Field(MSTinyInteger(3,unsigned=True),)
    longestchain=Field(MSTinyInteger(3,unsigned=True),)
    wienerind4=Field(MSFloat(16,14),)
    numbnd=Field(MSTinyInteger(3,unsigned=True),)
    numfrg=Field(MSTinyInteger(3,unsigned=True),)
    numrotbnd=Field(MSTinyInteger(3,unsigned=True),)
    mw=Field(MSFloat(8,3,unsigned=True),)
    clogp=Field(MSFloat(5,2,unsigned=True),)
    charge=Field(MSInteger(2))
    mol2file=Field(MSBlob,)
    #poses=OneToMany('Pose')
    tag=Field(MSChar(20))
  
    def writeMOL2(self,name=''):
        if name=='':
            name='zinc%d.mol2'%(self.zincid)
        f=open(name,'w')
        f.write(self.MOL2())
        f.close()
        return
  
    def MOL2(self):
        return zlib.decompress(self.mol2file)


class MOLTAG(Entity):
    '''
    Status:
    1 -- in process
    2 -- done
    3 -- error
    6 -- unhandled
    The status column should be 6 at first.
    '''
    using_options(tablename=settings.MoleculeTagTableName,autosetup=True)
    
    mol=ManyToOne('MOL')
    status=Field(INT,index=True)
    tag=Field(CHAR(20))
    
    def update(self,**argv):
        pk='id'
        pkv=self.id
        _updatetag(self.table.name,pk,pkv,**argv)

class POSE(Entity):
    using_options(tablename=settings.PoseTableName,autosetup=True)
    
    exec(_dic2cmd(settings.PoseColumn))
    
    pdbfile=Field(BLOB,deferred=True)
    mol=ManyToOne('MOL')
    tag=OneToOne('POSETAG')

class POSETAG(Entity):
    using_options(tablename=settings.PoseTagTableName,autosetup=True)
    
    pose=ManyToOne('POSE')
    status=Field(INT,index=True)
    tag=Field(CHAR(20))
    
    def update(self,**argv):
        pk='id'
        pkv=self.id
        _updatetag(self.table.name,pk,pkv,**argv)
 